---
title: 'wasm-bindgen'
sidebar_label: wasm-bindgen
---

[`wasm-bindgen`](https://github.com/rustwasm/wasm-bindgen) is a library and tool to facilitate
high-level interactions between Wasm modules and JavaScript; it is built with Rust by
[The Rust and WebAssembly Working Group](https://rustwasm.github.io/).

Yew uses `wasm-bindgen` to interact with the browser through a number of crates:

- [`js-sys`](https://crates.io/crates/js-sys)
- [`wasm-bindgen`](https://crates.io/crates/wasm-bindgen)
- [`wasm-bindgen-futures`](https://crates.io/crates/wasm-bindgen-futures)
- [`web-sys`](https://crates.io/crates/web-sys)

This section will explore some of these crates at a high level, to make it easier to understand
and use `wasm-bindgen` APIs with Yew. For a more in-depth guide to `wasm-bindgen` and its associated
crates then check out [The `wasm-bindgen` Guide](https://wasm-bindgen.github.io/wasm-bindgen/).

For documentation on the above crates check out [`wasm-bindgen docs.rs`](https://wasm-bindgen.github.io/wasm-bindgen/api/wasm_bindgen/index.html).

:::tip
Use the `wasm-bindgen` doc.rs search to find browser APIs and JavaScript types that have been imported
over using `wasm-bindgen`.
:::

## [`wasm-bindgen`](https://crates.io/crates/wasm-bindgen)

This crate provides many of the building blocks for the rest of the crates above. In this section we
are only going to cover two main areas of the `wasm-bindgen` crate and that is the macro and some
types/traits you will see pop up again and again.

### `#[wasm_bindgen]` macro

The `#[wasm_bindgen]` macro provides an interface between Rust and JavaScript, providing a system
for translating between the two. Using this macro is more advanced, and you should not need to reach
for it unless you are trying to use an external JavaScript library. The `js-sys` and `web-sys`
crates expose `wasm-bindgen` definitions for built-in JavaScript types and browser APIs.

Let's go over a simple example of using the `#[wasm-bindgen]` macro to import some specific flavours
of the [`console.log`](https://developer.mozilla.org/en-US/docs/Web/API/Console/log) function.

```rust ,no_run
use wasm_bindgen::prelude::*;

// First up let's take a look of binding `console.log` manually, without the
// help of `web_sys`. Here we're writing the `#[wasm_bindgen]` annotations
// manually ourselves, and the correctness of our program relies on the
// correctness of these annotations!
#[wasm_bindgen]
extern "C" {
    // Use `js_namespace` here to bind `console.log(..)` instead of just
    // `log(..)`
    #[wasm_bindgen(js_namespace = console)]
    fn log(s: &str);

    // The `console.log` is quite polymorphic, so we can bind it with multiple
    // signatures. Note that we need to use `js_name` to ensure we always call
    // `log` in JS.
    #[wasm_bindgen(js_namespace = console, js_name = log)]
    fn log_u32(a: u32);

    // Multiple arguments too!
    #[wasm_bindgen(js_namespace = console, js_name = log)]
    fn log_many(a: &str, b: &str);
}

// using the imported functions!
log("Hello from Rust!");
log_u32(42);
log_many("Logging", "many values!");
```

_This example was adapted from [1.2 Using console.log of The `wasm-bindgen` Guide](https://wasm-bindgen.github.io/wasm-bindgen/examples/console-log.html)_.

### Simulating inheritance

Inheritance between JavaScript classes is a core feature of the Javascript language and the DOM
(Document Object Model) is designed around it. When types are imported using `wasm-bindgen` you can
also add attributes that describe their inheritance.

In Rust, this inheritance is represented using the [`Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html)
and [`AsRef`](https://doc.rust-lang.org/std/convert/trait.AsRef.html) traits. An example of this
might help; so say you have three types `A`, `B`, and `C` where `C` extends `B` which in turn
extends `A`.

When importing these types the `#[wasm-bindgen]` macro will implement the `Deref` and `AsRef`
traits in the following way:

- `C` can `Deref` to `B`
- `B` can `Deref` to `A`
- `C` can be `AsRef` to `B`
- Both `C` & `B` can be `AsRef` to `A`

These implementations allow you to call a method from `A` on an instance of `C` and to use `C` as if
it was `&B` or `&A`.

It is important to note that every single type imported using `#[wasm-bindgen]` has the same root type,
you can think of it as the `A` in the example above, this type is [`JsValue`](https://wasm-bindgen.github.io/wasm-bindgen/api/wasm_bindgen/struct.JsValue.html) which has
its section below.

_[extends section in The `wasm-bindgen` Guide](https://wasm-bindgen.github.io/wasm-bindgen/reference/attributes/on-js-imports/extends.html)_

### [`JsValue`](https://wasm-bindgen.github.io/wasm-bindgen/api/wasm_bindgen/struct.JsValue.html)

This is a representation of an object owned by JavaScript, this is a root catch-all type for `wasm-bindgen`.
Because JavaScript does not have a strong type system, any type that comes from `wasm-bindgen` is a `JsValue`.
Functions in JavaScript do not define the type of any variables they take in or return; variables can be
any valid JavaScript value, hence `JsValue`. If you are working with imported functions or types that
accept a `JsValue`, then any imported value is _technically_ valid.

Even though `JsValue` may be accepted by a JS function, that function may still only _actually_ accept certain types.
Passing an incorrect `JsValue` can lead to an exception which triggers a panic - so when using raw `wasm-bindgen` APIs,
check the your JavaScript's documentation for types of inputs that will cause an exception (and a panic).

_[`JsValue` documentation](https://wasm-bindgen.github.io/wasm-bindgen/api/wasm_bindgen/struct.JsValue.html)._

### [`JsCast`](https://wasm-bindgen.github.io/wasm-bindgen/api/wasm_bindgen/trait.JsCast.html)

Rust has a strong type system and JavaScript...doesn't 😞. For Rust to maintain these
strong types but still be convenient, the WebAssembly group came up with a pretty neat trait `JsCast`.
Its job is to help you move from one JavaScript "type" to another, which sounds vague, but it means
that if you have one type which you know is another, then you can use the functions of `JsCast`
to jump from one type to the other. It is a nice trait to get to know when working with `web-sys`,
`wasm_bindgen`, `js-sys` - you will notice lots of types will implement `JsCast` from those crates.

`JsCast` provides both checked and unchecked methods of casting - so if at runtime if you are
unsure what type a certain object is, you can try to cast it, which returns possible failure types like
[`Option`](https://doc.rust-lang.org/std/option/enum.Option.html) and
[`Result`](https://doc.rust-lang.org/std/result/enum.Result.html).

A common example of this in [`web-sys`](./web-sys.mdx) is when you are trying to get the
target of an event. You might know what the target element is, but the
[`web_sys::Event`](https://wasm-bindgen.github.io/wasm-bindgen/api/web_sys/struct.Event.html) API will always return an [`Option<web_sys::EventTarget>`](https://wasm-bindgen.github.io/wasm-bindgen/api/web_sys/struct.Event.html#method.target).
You will need to cast it to the element type so you can call its methods.

```rust
// need to import the trait.
use wasm_bindgen::JsCast;
use web_sys::{Event, EventTarget, HtmlInputElement, HtmlSelectElement};

fn handle_event(event: Event) {
    let target: EventTarget = event
        .target()
        .expect("I'm sure this event has a target!");

    // maybe the target is a select element?
    if let Some(select_element) = target.dyn_ref::<HtmlSelectElement>() {
        // do something amazing here
        return;
    }

    // if it wasn't a select element then I KNOW it's a input element!
    let input_element: HtmlInputElement = target.unchecked_into();
}
```

The [`dyn_ref`](https://wasm-bindgen.github.io/wasm-bindgen/api/wasm_bindgen/trait.JsCast.html#method.dyn_ref)
method is a checked cast that returns an `Option<&T>`, which means the original type
can be used again if the cast failed and thus returned `None`. The
[`dyn_into`](https://wasm-bindgen.github.io/wasm-bindgen/api/wasm_bindgen/trait.JsCast.html#method.dyn_into)
method will consume `self`, as per convention for `into` methods in Rust, and the type returned is
`Result<T, Self>`. If the casting fails, the original `Self` value is returned in `Err`. You can try again
or do something else with the original type.

_[`JsCast` documentation](https://wasm-bindgen.github.io/wasm-bindgen/api/wasm_bindgen/trait.JsCast.html)._

### [`Closure`](https://wasm-bindgen.github.io/wasm-bindgen/api/wasm_bindgen/closure/struct.Closure.html)

The `Closure` type provides a way to transfer Rust closures to JavaScript. The closures passed to
JavaScript must have a `'static` lifetime for soundness reasons.

This type is a "handle" in the sense that whenever it is dropped, it will invalidate the JS
closure that it refers to. Any usage of the closure in JS after the Closure has been dropped will
raise an exception.

`Closure` is often used when you are working with a `js-sys` or `web-sys` API that accepts a type
[`&js_sys::Function`](https://wasm-bindgen.github.io/wasm-bindgen/api/js_sys/struct.Function.html).
An example of using a `Closure` in Yew can be found in the [Using `Closure` section](../html/events.mdx#using-closure-verbose)
on the [Events](../html/events.mdx) page.

_[`Closure` documentation](https://wasm-bindgen.github.io/wasm-bindgen/api/wasm_bindgen/closure/struct.Closure.html)._

## [`js-sys`](https://crates.io/crates/js-sys)

The `js-sys` crate provides bindings/imports of JavaScript's standard, built-in objects, including
their methods and properties.

This does not include any web APIs; that's what [`web-sys`](./web-sys.mdx) is for!

_[`js-sys` documentation](https://wasm-bindgen.github.io/wasm-bindgen/api/js_sys/index.html)._

## [`wasm-bindgen-futures`](https://crates.io/crates/wasm-bindgen-futures)

The `wasm-bindgen-futures` crate provides a bridge for working with JavaScript Promise types as a
Rust [`Future`](https://doc.rust-lang.org/stable/std/future/trait.Future.html), and contains
utilities to turn a rust Future into a JavaScript Promise. This can be useful when working with
asynchronous or otherwise blocking work in Rust (wasm), and provides the ability to interoperate
with JavaScript events and JavaScript I/O primitives.

There are three main interfaces in this crate currently:

1. [`JsFuture`](https://wasm-bindgen.github.io/wasm-bindgen/api/wasm_bindgen_futures/struct.JsFuture.html) -
   A type that is constructed with a [`Promise`](https://wasm-bindgen.github.io/wasm-bindgen/api/js_sys/struct.Promise.html)
   and can then be used as a `Future<Output=Result<JsValue, JsValue>>`. This `Future` will resolve to `Ok` if
   the `Promise` is resolved and `Err` if the `Promise` is rejected, containing the resolved or rejected
   value from the `Promise` respectively.

2. [`future_to_promise`](https://wasm-bindgen.github.io/wasm-bindgen/api/wasm_bindgen_futures/fn.future_to_promise.html) -
   Converts a Rust `Future<Output=Result<JsValue, JsValue>>` into a
   JavaScript `Promise`. The future’s result will translate to either a resolved or rejected
   `Promise` in JavaScript.

3. [`spawn_local`](https://wasm-bindgen.github.io/wasm-bindgen/api/wasm_bindgen_futures/fn.spawn_local.html) -
   Spawns a `Future<Output = ()>` on the current thread. This is the best way
   to run a Future in Rust without sending it to JavaScript.

_[`wasm-bindgen-futures` documentation](https://wasm-bindgen.github.io/wasm-bindgen/api/wasm_bindgen_futures/index.html)._

### [`spawn_local`](https://wasm-bindgen.github.io/wasm-bindgen/api/wasm_bindgen_futures/fn.spawn_local.html)

`spawn_local` is going to be the most commonly used part of the `wasm-bindgen-futures` crate in Yew
as this helps when using libraries that have async APIs.

```rust ,no_run
use web_sys::console;
use wasm_bindgen_futures::spawn_local;

async fn my_async_fn() -> String { String::from("Hello") }

spawn_local(async {
    let mut string = my_async_fn().await;
    string.push_str(", world!");
    // console log "Hello, world!"
    console::log_1(&string.into());
});
```

Yew has also added support for futures in certain APIs, most notably you can create a
`callback_future` which accepts an `async` block - this uses `spawn_local` internally.

_[`spawn_local` documentation](https://wasm-bindgen.github.io/wasm-bindgen/api/wasm_bindgen_futures/fn.spawn_local.html)._
